'''
Created on 14.11.2011

@author: halldor
'''
'''
Created on 13.11.2011

@author: halldor
'''
from datetime import date
from calendar import monthrange
from Calendar.Iceland import Iceland
from TimeUtils.daterolling import *

def addmonth2(ddate, monthstoadd, caldar, daterollingconvention, businessdays=1):
    '''
    Adding months to a date, we assume monthstoadd>=0 (whole numbers)
    Based on BBA Libor rules for value and maturity dates. We accept ddate as the value date to use.
    1) We account for holidays according to caldar
    2) We dont restrict daterollingconvention and therefor not restricted to modified following business day convention
    3) For all maturity days, they cannot roll-over into a new calendar month from the value date. We roll back to
       latest available business day in month.
    (NOTE: By above, we 
    Parameters: 
        ddate:                   date to add months too
        monthstoadd:             number of months to add
        caldar:                  calendar to use (instance of Calendar)
        ddaterollingconvention:  date rolling convention (actual, modified, modified following, 
                                                          preceding, modified preceding)
        businessdays:            if businessdays=1, we roll back by 2) and 3) according to caldar business days, 
                                 else we don't but use last day in maturity month if ddate day is greater and actual 
                                 daterolling applies for all other daytes (no daterolling)
    Returns:
        date where ddate has been advanced by monthstoadd
    '''
    year    = ddate.year
    month   = ddate.month
    day     = ddate.day

    addyear = 0
    monthcount = month + monthstoadd
    
    while monthcount > 12:
        monthcount -= 12
        addyear +=1
    
    newmonth = monthcount
    newyear = year + addyear
    
    newdate = 0
    
    temp = monthrange(year, month)
    daysinmonth = temp[1]
    
    temp = monthrange(newyear, newmonth)
    newdaysinmonth = temp[1]
    
    lastbusdayofmonth =  preceding(caldar, date(year, month, daysinmonth))

    if businessdays == 1:
        if (day == lastbusdayofmonth.day) or (day>newdaysinmonth):
            newlastbusdayofmonth =  preceding(caldar, date(newyear, newmonth, newdaysinmonth))
            newdate = date(newyear, newmonth, newlastbusdayofmonth.day)
        else:
            newdate = date(newyear, newmonth, day)
            if daterollingconvention == DateRollingConvention.following:
                newdate = following(caldar, newdate)
            elif daterollingconvention == DateRollingConvention.modifiedfollowing:
                newdate = modifiedfollowing(caldar, newdate)
            elif daterollingconvention == DateRollingConvention.preceding:
                newdate = preceding(caldar, newdate)
            elif daterollingconvention == DateRollingConvention.modifiedpreceding:
                newdate = modifiedpreceding(caldar, newdate)
            else:
                newdate = date(newyear, newmonth, day)
    else:
        if day>newdaysinmonth:
            newdate = date(newyear, newmonth, newdaysinmonth)
        else:
            newdate = date(newyear, newmonth, day)
            
    return newdate

cal = Iceland()
daterollingconvention = DateRollingConvention.modifiedfollowing

#ddate = date(2011,5,31)
ddate = date(2012,2,13)
print addmonth2(ddate,12, cal, daterollingconvention,1)

